package com.jie.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jie.dto.ArticleDTO;
import com.jie.entity.Article;
import com.jie.entity.Tag;
import com.jie.enums.ArticleFlowEvent;
import com.jie.enums.ArticleStatusEnum;
import com.jie.mapper.ArticleFileMapper;
import com.jie.mapper.ArticleMapper;
import com.jie.mapper.ArticleTagMapper;
import com.jie.mapper.TagMapper;
import com.jie.po.req.ArticleReq;
import com.jie.service.IArticleService;
import com.jie.service.ITagService;
import com.jie.state.ArticleStateServiceImpl;
import com.jie.state.StateConstants;
import com.jie.utils.BeanCopyUtils;
import com.jie.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.jie.constants.RedisArticleConst.ARTICLE_HISTORY_KEY;

/**
 * <p>
 * 论坛文章表 服务实现类
 * </p>
 *
 * @author jie
 * @since 2024-05-29
 */
@Service
@Slf4j
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements IArticleService {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private ITagService tagService;
    @Autowired
    private ArticleTagMapper articleTagMapper;
    @Autowired
    private ArticleFileMapper articleFileMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ArticleStateServiceImpl articleStateService;
    @Autowired
    private ArticleMapper articleMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addArticle(ArticleReq articleReq) {
        //判断是否公开发布
        if (Objects.equals(articleReq.getStatus(), ArticleStatusEnum.PUBLIC.getStatus())) {
            //1.保存文章信息
            Integer articleId = addOrUpdateArticleInfo(articleReq);
            articleReq.setId(articleId);
            Article article = BeanCopyUtils.copyObject(articleReq, Article.class);
            //2. 脱敏 通过状态机转换状态 从保存->脱敏
            if (articleStateService.sendEvent(ArticleFlowEvent.REPLACE, article,StateConstants.REPLACE)){
                article.setArticleContent(algorithmReplaceSensitiveWord(article.getArticleContent()));
            }
            //3.进入审核 内部走到mq去做
            articleStateService.sendEvent(ArticleFlowEvent.AUDIT, article,StateConstants.AUDIT);
            //这里假设在mq里面 mq里面在做审核成功或失败来进行发送
        }else {
            //私密文章不需要审核
            addOrUpdateArticleInfo(articleReq);
        }
    }
    // 判断文章状态并处理
    // 假设我们有以下方法
    @Override
    public boolean aigcApprovedArticleInfo(Article article) {
        boolean flag=true;
        if (true){
            // 假设审核通过
            articleStateService.sendEvent(ArticleFlowEvent.AUDIT_SUCCESS, article,StateConstants.AUDIT_SUCCESS);
        }else{
            articleStateService.sendEvent(ArticleFlowEvent.AUDIT_FAIL, article,StateConstants.AUDIT_FAIL);
        }
        return flag;
    }

    @Override
    public List<ArticleDTO> getArticleList() {
        return articleMapper.selectArticleList();
    }

    @Override
    public boolean addArticleCommentCount(Integer articleId, Integer commentCount) {
        return articleMapper.addCommentCount(articleId, commentCount);
    }

    private String algorithmReplaceSensitiveWord(String content) {
        // 敏感词替换逻辑
        return content; // 假设替换完成
    }

    /**
     * 添加或删除资源
     * @param articleReq
     * @return
     */
    public Integer addOrUpdateArticleInfo(ArticleReq articleReq) {
        Integer userId = UserUtils.getLoginUser().getId();
        //1.保存文章信息
        Article article = BeanCopyUtils.copyObject(articleReq, Article.class);
        article.setUserId(userId);
        this.saveOrUpdate(article);
        //判断redis是否有这个文章的历史信息，如果有就是草稿箱的 不需要重新加载这两块
        SetOperations setOperations = redisTemplate.opsForSet();
        if (Boolean.FALSE.equals(setOperations.isMember(ARTICLE_HISTORY_KEY+userId,article.getId()))) {
            //存入文件资源信息
            saveArticleResource(articleReq, article.getId());
            //2.存入标签信息
            saveArticleTag(articleReq, article.getId());
            //3.存入redis中做历史记录
            setOperations.add(ARTICLE_HISTORY_KEY+userId, article.getId());
        }
        return article.getId();
    }



    private void saveArticleResource(ArticleReq articleReq, Integer articleId) {
        //资源ids
        List<Integer> fileIds = articleReq.getFileIds();
        if (CollectionUtils.isNotEmpty(fileIds)){
            //加入资源中间表
            articleFileMapper.saveBatchFileResource(articleId,fileIds);
        }
    }

    public void saveArticleTag(ArticleReq article, Integer articleId) {
        List<String> tagNameList = article.getTagNameList();
        if (CollectionUtils.isNotEmpty(tagNameList)) {
            // 查询出已存在的标签
            List<Tag> existTagList = tagMapper.selectTagList(tagNameList);
            List<String> existTagNameList = existTagList.stream()
                    .map(Tag::getTagName)
                    .collect(Collectors.toList());
            List<Integer> existTagIdList = existTagList.stream()
                    .map(Tag::getId)
                    .collect(Collectors.toList());
            // 移除已存在的标签列表
            tagNameList.removeAll(existTagNameList);
            // 含有新标签
            if (CollectionUtils.isNotEmpty(tagNameList)) {
                // 新标签列表
                List<Tag> newTagList = tagNameList.stream()
                        .map(item -> Tag.builder()
                                .tagName(item)
                                .build())
                        .collect(Collectors.toList());
                // 批量保存新标签
                tagService.saveBatch(newTagList);
                // 获取新标签id列表
                List<Integer> newTagIdList = newTagList.stream()
                        .map(Tag::getId)
                        .collect(Collectors.toList());
                // 新标签id添加到id列表
                existTagIdList.addAll(newTagIdList);
            }
            // 将所有的标签绑定到文章标签关联表
            articleTagMapper.saveBatchArticleTag(articleId, existTagIdList);
        }
    }

}
